import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  CreateDateColumn,
  UpdateDateColumn,
  JoinColumn,
  ManyToOne,
} from 'typeorm';
import { ApiHideProperty, ApiProperty } from '@nestjs/swagger';
import {
  IsArray,
  IsEmpty,
  IsEnum,
  IsNumber,
  IsOptional,
  IsString,
  ValidateNested,
} from 'class-validator';

import { PunchFood, Category } from '@/modules/app/entities';
import { Type } from 'class-transformer';

// 营养素类型枚举
export enum NutrientType {
  /** 热量（千卡）*/
  CALORIES = 'CALORIES',
  /** 碳水化合物（克） */
  CARBS = 'CARBS',
  /** 蛋白质（克） */
  PROTEIN = 'PROTEIN',
  /** 胆固醇（毫克） */
  CHOLESTEROL = 'CHOLESTEROL',
  /** 脂肪（克） */
  FAT = 'FAT',
  /** 纤维素（g） */
  FIBER = 'FIBER',
  /** 叶酸（μg） */
  FOLATE = 'FOLATE',
  /** 铁（mg） */
  IRON = 'IRON',
  /** 镁（mg） */
  MAGNESIUM = 'MAGNESIUM',
  /** 维生素 B12（μg） */
  VITAMIN_B12 = 'VITAMINB12',
  /** 维生素 B6（mg） */
  VITAMIN_B6 = 'VITAMINB6',
  /** β-胡萝卜素（μg） */
  BETA_CAROTENE = 'BETACAROTENE',
  /** 单不饱和脂肪酸（g） */
  MUFA = 'MUFA',
  /** 烟酸（mg） */
  NIACIN = 'NIACIN',
  /** n-3 脂肪酸（g） */
  OMEGA3 = 'OMEGA3',
  /** 多不饱和脂肪酸（g） */
  PUFA = 'PUFA',
  /** 核黄素（mg） */
  RIBOFLAVIN = 'RIBOFLAVIN',
  /** 饱和脂肪酸（g） */
  SFA = 'SFA',
  /** 硒（μg） */
  SELENIUM = 'SELENIUM',
  /** 硫胺（mg） */
  THIAMINE = 'THIAMINE',
  /** 维生素 A（μg） */
  VITAMIN_A = 'VITAMINA',
  /** 维生素 C（mg） */
  VITAMIN_C = 'VITAMINC',
  /** 维生素 D（μg） */
  VITAMIN_D = 'VITAMIND',
  /** 维生素 E（mg） */
  VITAMIN_E = 'VITAMINE',
  /** 锌（mg） */
  ZINC = 'ZINC',
}

/**
 * 开启了脚本，省略了以下，不走脚本需要加下面内容，去除 [= 0];
 * @IsOptional()
 * @Column({ type:number, default: 0 })
 * 其中?可选是给dto校验的可选，如果要穿参数为空需要  @Column({ nullable: true })
 */
export class NutrientItem {
  @ApiProperty({
    description: `营养素类型:
    CALORIES:热量
    CARBS:碳水化合物
    PROTEIN:蛋白质
    CHOLESTEROL:胆固醇
    FAT:脂肪
    FIBER:纤维素
    FOLATE:叶酸
    IRON:铁
    MAGNESIUM:镁
    VITAMIN_B12:维生素 B12
    VITAMIN_B6:维生素 B6
    BETA_CAROTENE:β-胡萝卜素
    MUFA:单不饱和脂肪酸
    NIACIN:烟酸
    OMEGA3:n-3 脂肪酸
    PUFA:多不饱和脂肪酸
    RIBOFLAVIN:核黄素
    SFA:饱和脂肪酸
    SELENIUM:硒
    THIAMINE:硫胺
    VITAMIN_A:维生素 A
    `,
    enum: NutrientType,
    example: NutrientType.CALORIES,
  })
  /**
   * 营养素类型
   */
  @IsEnum(NutrientType)
  @Column()
  type: NutrientType;

  /**
   * 营养素含量
   */
  @IsOptional()
  @IsNumber()
  @Column({ type: 'float', nullable: true, default: 0 })
  amount?: number = 0;

  /**
   * 营养素炎症指数
   */
  @IsOptional()
  @IsNumber()
  @Column({ type: 'float', nullable: true, default: 0 })
  inflammationIndex?: number = 0;

  /**
   * 单位
   */
  @IsString()
  @Column({ default: '' })
  unit?: string;
}

@Entity('food')
export class Food {
  @PrimaryGeneratedColumn('increment')
  foodId: number;

  /**
   * 食物名称
   */
  @IsString()
  @Column()
  name: string;

  /**
   * 食物图片
   */
  @IsString()
  @Column()
  imageUrl: string;

  /**
   * 食物标签
   * 午餐、晚餐、加餐
   * @example 午餐
   */
  @IsString()
  @Column()
  @IsOptional()
  tag?: string;

  /**
   * 食物单位
   */
  @ApiProperty({ default: '100g' })
  @IsString()
  @IsOptional()
  @Column({ default: '100g' })
  unit?: string;

  /**
   * 食物分类 ID
   */
  @IsNumber()
  @Column({
    nullable: true,
  })
  categoryId: number;

  /**
   * 食物分类
   */
  @ApiHideProperty()
  @ManyToOne(() => Category, (category) => category.foods, { nullable: true })
  @JoinColumn({ name: 'categoryId' })
  category?: Category;

  /**
   * 微量元素
   */
  // ! mysql不建议用json，他会浪费空间，并且只有 mysql8 以上才支持，待验证
  @IsArray()
  @ValidateNested({ each: true }) // 启用嵌套对象的校验
  @Type(() => NutrientItem) // 指定嵌套对象的类型
  @Column({ type: 'json' })
  microElement?: NutrientItem[];

  /**
   * 关联日志
   */
  @ApiHideProperty()
  @OneToMany(() => PunchFood, (dietFood) => dietFood.food)
  punchFoods: PunchFood[];

  @CreateDateColumn()
  createdAt?: Date;

  @UpdateDateColumn()
  updatedAt?: Date;

  @ApiHideProperty()
  @Column({ default: false, select: false })
  isDeleted?: boolean;
}
